package com.tan.config;

import com.alibaba.fastjson.JSON;
import com.tan.util.IpUtils;
import io.swagger.models.HttpMethod;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * @author tlj
 * @date 2022/08/19 16:19:33
 */
@Aspect
@Component
@Slf4j
// @Order(2)
public class LogAspect {

    @Autowired
    private HttpServletRequest request;


    @Pointcut("execution(* com.tan.controller..*(..))")
    public void webData() {

    }

    @Around(value = "webData()")
    public Object aroundWebData(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = null;
        Exception ex = null;
        String param = "";
        try {
            param = getRequestParams(proceedingJoinPoint, request.getMethod());
            result = proceedingJoinPoint.proceed();
        } catch (Exception e) {
            ex = e;
            throw e;
        } finally {
            handleLog(proceedingJoinPoint, ex, result, param, startTime);
        }
        return result;
    }

    /**
     * 处理日志
     */
    protected void handleLog(final JoinPoint joinPoint, final Exception e, final Object resultData, final String params, long millis) {
        try {
            //请求地址
            String url = request.getRequestURI();
            // 获取当前的用户
            String employeeCode = null;
            if (StringUtils.isEmpty(url)) {
                employeeCode = "";
            }
            // 请求的地址
            String ip = IpUtils.getRemoteIP(request);
            // 返回参数
            String resStr = JSON.toJSONString(resultData);

            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            // 设置请求方式
            String method = request.getMethod();
            //请求参数
            //String params = getRequestParams(joinPoint, method);
            long ms = System.currentTimeMillis() - millis;
            String info = "[" + ip + "],[" + method + "],[耗时:" + ms + "][" + employeeCode + "]," +
                    "url:[" + url + "],method:[" + className + "." + methodName + "()],params:" + params + ",";
            //返回结果
            if (e != null) {
                info += "Exception:[" + e.getMessage() + "]";
                log.info(info);
            } else {
                info += "resultData:" + (resStr.length() > 2000 ? "数据太长不打印" : resStr);
                log.info(info);
            }
            //性能打印
            // if (ms > projectConfig.getRequestTimeout()) {
            //     logger.info(info);
            // }
        } catch (Exception exp) {
            // 记录本地异常日志
            log.error("日志异常信息:", exp);
        }
    }

    /**
     * 获取请求的参数
     *
     * @throws Exception 异常
     */
    private String getRequestParams(JoinPoint joinPoint, String method) throws UnsupportedEncodingException {
        String param = "";
        if (HttpMethod.PUT.name().equals(method)) {
            param = argsArrayToString(joinPoint.getArgs());
        } else {
            String decode = "";
            if (request.getQueryString() != null) {
                decode = URLDecoder.decode(request.getQueryString(), "utf-8");
                param = "{" + decode + "}";
            }
        }
        return param;
    }

    /**
     * 参数拼装
     *
     * @param paramsArray
     * @return
     */
    private String argsArrayToString(Object[] paramsArray) {
        StringBuilder param = new StringBuilder();
        if (paramsArray != null && paramsArray.length > 0) {
            for (int i = 0; i < paramsArray.length; i++) {
                if (!isFilterObject(paramsArray[i])) {
                    Object jsonObject = JSON.toJSON(paramsArray[i]);
                    param.append(jsonObject != null ? jsonObject.toString() : "" + " ");
                }
            }
        }
        return param.toString().trim();
    }

    /**
     * 判断是否是需要过滤的对象
     *
     * @param o 对象信息
     * @return 是要过滤的对象，返回 true;否则返回false
     */
    public boolean isFilterObject(final Object o) {
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
    }
}









































